package com.example.core.controller;

import com.example.core.convert.context.RequestContext;
import com.example.core.form.BaseForm;
import com.example.core.hql.HQLInfo;
import com.example.core.model.BaseModel;
import com.example.core.service.BaseService;
import com.example.utils.Page;
import com.example.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class BaseController<S extends BaseService, F extends BaseForm> {

    public static final String PREF = "/";

    @Autowired
    private S service;

    @GetMapping("add")
    public String add(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
        try {
            this.createNewForm(new RequestContext(httpServletRequest, httpServletResponse));
            return this.getModelForward("edit");
        } catch (Exception e) {
            httpServletRequest.setAttribute("error", e.getMessage());
            return this.getForward("error");
        }
    }

    @GetMapping("edit")
    public String edit(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
        try {
            this.loadActionModel(new RequestContext(httpServletRequest, httpServletResponse));
            return this.getModelForward("edit");
        } catch (Exception e) {
            httpServletRequest.setAttribute("error", e.getMessage());
            return this.getForward("error");
        }
    }

    @GetMapping("view")
    public String view(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
        try {
            this.loadActionModel(new RequestContext(httpServletRequest, httpServletResponse));
            return this.getModelForward("view");
        } catch (Exception e) {
            httpServletRequest.setAttribute("error", e.getMessage());
            return this.getForward("error");
        }
    }

    @GetMapping("index")
    public String index(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
        return this.getModelForward("index");
    }

    @PostMapping("save")
    public String save(F form, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
        try {
            this.service.add(form, new RequestContext(httpServletRequest, httpServletResponse));
            return this.getForward("success");
        } catch (Exception e) {
            e.printStackTrace();
            httpServletRequest.setAttribute("error", e.getMessage());
            return this.getForward("error");
        }
    }

    @ResponseBody
    @RequestMapping("data")
    public Page data(F form, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
        Page page = null;
        try {
            HQLInfo info = new HQLInfo();
            this.changeFindPageHQLInfo(form, new RequestContext(httpServletRequest, httpServletResponse), info);
            page = this.service.findPage(info);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return page;
    }

    protected void createNewForm(RequestContext requestContext) throws Exception {
        BaseForm baseForm = this.service.initFormSetting(requestContext);
        initPageParameter(requestContext, baseForm);
    }

    protected String getFormName(Object form) {
        String formName = form.getClass().getName();
        formName = formName.substring(formName.lastIndexOf('.') + 1);
        return formName.substring(0, 1).toLowerCase() + formName.substring(1);
    }

    protected void loadActionModel(RequestContext requestContext) throws Exception {
        String id = requestContext.getParameter("id");
        if (!StringUtils.isEmpty(id)) {
            BaseModel baseModel = this.service.findByPrimaryKey(id, Boolean.TRUE);
            BaseForm baseForm = this.service.convertModelToForm(baseModel, requestContext);
            initPageParameter(requestContext, baseForm);
        }
    }

    protected void changeFindPageHQLInfo(BaseForm form, RequestContext requestContext, HQLInfo info) {
        info.setPageNum(form.getPage());
        info.setPageSize(form.getLimit());
        String fdName = requestContext.getParameter("fdName");
        if (!StringUtils.isEmpty(fdName)) {
            info.setWhereBlock(" fdName like :fdName");
            info.setParameter("fdName", "%" + fdName + "%");
        }
    }

    protected void initPageParameter(RequestContext requestContext, BaseForm baseForm) {
        requestContext.setAttribute("entityName", this.service.getEntityClass().getSimpleName());
        requestContext.setAttribute("formName", getFormName(baseForm));
        requestContext.setAttribute(getFormName(baseForm), baseForm);
    }

    public String getForward(String forward) {
        return forward;
    }

    public String getModelForward(String forward) {
        return this.service.getEntity() + PREF + forward;
    }

    public S getService() {
        return service;
    }
}
